<!--
  This demonstrates the effectiveness a method for testing for visibility elements on various
  conditions.
-->
<!DOCTYPE html>
<html>
  <head>
    <title>Visibility test</title>
    <link rel="icon" href="data:;base64,iVBORw0KGgo=">
    <style type="text/css" media="screen">
      * {
        font-family: sans;
        font-size: 14px;
      }
      span {
        display: block;
        width: 30px;
        height: 20px;
        background-color: blue;
      }
      table {
        border-collapse: separate;
      }
      tr, td {
        border: 2px solid black;
        margin: 0;
        padding: 2px;
      }
    </style>

    <script charset="utf-8">
      window.addEventListener("load", displayTests, false);
      window.addEventListener("load", checkDivsForVisibility, false);

      var visibilityTests = [
        {
          "description": "BoundingClientRect is inside viewport",
          "test": function (element) {
            var rect = element.getBoundingClientRect();
            if (
              !rect || rect.top > window.innerHeight || rect.bottom < 0 ||
              rect.left > window.innerWidth || rect.right < 0
            ) {
              return false;
            }
            return true;
          },
        },
        {
          "description": "BoundingClientRect has nonzero dimensions",
          "test": function (element) {
            var rect = element.getBoundingClientRect();
            if (!rect || rect.width == 0 || rect.height == 0) {
              return false;
            }
            return true;
          },
        },
        {
          "description": "Is visible and displayed",
          "test": function (element) {
            var computedStyle = window.getComputedStyle(element, null);
            if (
              computedStyle.getPropertyValue("visibility") != "visible" ||
              computedStyle.getPropertyValue("display") == "none"
            ) {
              return false;
            }
            return true;
          },
        },
        {
          "description": "Has ClientRect",
          "test": function (element) {
            var clientRect = element.getClientRects()[0];
            if (!clientRect) {
              return false;
            }
            return true;
          },
        },
        {
          "description": "ClientRect has nonzero dimensions",
          "test": function (element) {
            var clientRect = element.getClientRects()[0];
            if (!clientRect || clientRect.width == 0 || clientRect.height == 0) {
              return false;
            }
            return true;
          },
        },
      ];

      function displayTests() {
        for (var i = 0; i < visibilityTests.length; i++) {
          document.getElementById("testDescriptions").innerHTML += "<b>Test " + (i + 1) +
            ": </b>" + visibilityTests[i].description + "<br/>";
        }
      }

      function makeBoolTd(bool) {
        var td = document.createElement("td");
        td.style.width = "15px";
        td.style.background = bool ? "#0f0" : "#f00";
        return td;
      }

      function makeTag(tag, text) {
        var td = document.createElement(tag);
        td.innerHTML = text;
        return td;
      }

      function checkDivsForVisibility() {
        var table = document.getElementById("resultsDisplay");
        var tr = document.getElementsByTagName("tr")[0];
        for (var i = 0; i < visibilityTests.length; i++) {
          tr.appendChild(makeTag("th", i + 1));
        }
        tr.appendChild(makeTag("th", "Expected Result"));
        tr.appendChild(makeTag("th", "Comments"));

        var divs = document.getElementsByClassName("testElement");
        for (var i = 0; i < divs.length; i++) {
          var tr = document.createElement("tr");
          table.appendChild(tr);
          table.appendChild(makeTag("td", i + 1));
          var netResult = true;
          for (var j = 0; j < visibilityTests.length; j++) {
            result = visibilityTests[j].test(divs[i]);
            table.appendChild(makeBoolTd(result));
            netResult = netResult && result;
          }
          var expectedResult = divs[i].getAttribute("data-expectedresult") == 1;
          var td = makeTag("td", expectedResult);
          td.style.background = netResult === expectedResult ? "#fff" : "#ccf";
          table.appendChild(td);
          table.appendChild(makeTag("td", divs[i].getAttribute("data-comment")));

          // hide the test cases once we're done with them
          divs[i].style.visibility = "hidden";
        }
      }
    </script>
  </head>

  <body>
    <div id="testDescriptions" style="margin: 6px 0 6px 0"></div>
    <table id="resultsDisplay">
      <tr>
        <th>Node/Test</th>
      </tr>
    </table>

    <div id="testContainer" style="position: absolute; top: 0; left: 0">
      <span class="testElement" data-expectedresult="1" data-comment="default">test</span>

      <span
        class="testElement"
        data-expectedresult="0"
        style="visibility: hidden"
        data-comment="visibility: hidden"
      >test</span>

      <div style="visibility: hidden">
        <span
          class="testElement"
          data-expectedresult="0"
          data-comment="nested in an element that has visibility: hidden"
        >test</span>
      </div>

      <span
        class="testElement"
        data-expectedresult="0"
        style="display: none"
        data-comment="display: none"
      >test</span>

      <div style="display: none">
        <span
          class="testElement"
          data-expectedresult="0"
          data-comment="nested in an element that has display: none"
        >test</span>
      </div>

      <span
        class="testElement"
        data-expectedresult="0"
        style="position: absolute; top: 2000px"
        data-comment="outside viewport"
      >test</span>

      <div style="opacity: 0">
        <span
          class="testElement"
          data-expectedresult="1"
          data-comment="nested in an element that has opacity:0"
        >test</span>
      </div>
      <div
        class="testElement"
        data-expectedresult="1"
        data-comment="Contains only a floated span. We must recurse into the div to find it."
      >
        <span style="float: left">test</span>
      </div>
      <svg>
        <a
          class="testElement"
          data-expectedresult="1"
          xlink:href="http://www.example.com/"
          data-comment="This link is contained within an SVG."
        >
          <text x="0" y="68">test</text>
        </a>
      </svg>
    </div>
  </body>
</html>
